﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Adams.Shared;

namespace Adams.Web.Logic.Security
{
    public class Login
    {
        private const int _AllowedLoginAttempts = 5;
        private const int _LockoutIncrementInMinutes = 5;

        public static Models.Security.Login.PageLoad PageLoad()
        {
            var model = new Adams.Web.Models.Security.Login.PageLoad();
            return model;
        }

        public static Models.Security.Login.FormOutput TryLogin(Models.Security.Login.FormInput input)
        {
            var output = new Models.Security.Login.FormOutput();
            Validation.PerformBasicValidation(input, (Models.FormOutput)output);

            if (output.IsValid)
            {
                var data = Data.Security.Common.GetMemberInfo(input.Email);

                if (data.Exists)
                {
                    // User does exist
                    if (data.IsEmailConfirmed)
                    {
                        // User does exist
                        if (data.IsActive)
                        {
                            // User is active
                            // Check if account is locked
                            if (Adams.Shared.SecurityHelper.IsLocked(data.FailedLoginAttempts, data.LastLoginAttempt, _AllowedLoginAttempts, _LockoutIncrementInMinutes))
                            {
                                // User is locked out
                                output.LockWaitMinutes = Adams.Shared.SecurityHelper.GetLockWaitMinutes(data.FailedLoginAttempts, data.LastLoginAttempt, _AllowedLoginAttempts, _LockoutIncrementInMinutes);
                                output.InvalidFields.Add(new Models.InvalidField() { Name = "Email", Code = 22 });
                            }
                            else
                            {
                                // Check if password is valid
                                string hashedPassword = Adams.Shared.Encryption.HashPassword(input.Password, data.PasswordSalt);
                                bool isPasswordValid = Shared.Str.IsEqual(hashedPassword, data.PasswordHash);

                                if (isPasswordValid)
                                {
                                    // Login Successful
                                    output.MemberID = data.MemberID;
                                    Data.Security.Login.ClearLockout(data.MemberID); // Clear lockout info
                                }
                                else
                                {
                                    // Invalid password
                                    Data.Security.Login.UpdateLockout(data.MemberID); // Update lockout info
                                    data.FailedLoginAttempts++;
                                    output.InvalidFields.Add(new Models.InvalidField() { Name = "Password", Code = 23 });

                                    if (data.FailedLoginAttempts >= _AllowedLoginAttempts)
                                    {
                                        output.LockWaitMinutes = Adams.Shared.SecurityHelper.GetLockWaitMinutes(data.FailedLoginAttempts, DateTime.UtcNow, _AllowedLoginAttempts, _LockoutIncrementInMinutes);
                                        output.InvalidFields.Add(new Models.InvalidField() { Name = "Email", Code = 22 });
                                    }
    
                                    output.AttemptsLeft = _AllowedLoginAttempts - data.FailedLoginAttempts;
                                }
                            }
                        }
                        else
                        {
                            output.InvalidFields.Add(new Models.InvalidField() { Name = "Email", Code = 24 });
                        }
                    }
                    else
                    {
                        output.InvalidFields.Add(new Models.InvalidField() { Name = "Email", Code = 19 });
                    }
                }
                else
                {
                    output.InvalidFields.Add(new Models.InvalidField() { Name = "Email", Code = 20 });
                }
            }

            return output;
        }
    }
}
